package oauth

import (
	"bytes"
	"fmt"
	"net/http"
	"net/url"

	"chainmaker.org/chainmaker/smarteditor/conf"
	"chainmaker.org/chainmaker/smarteditor/oauth/gitlab"
	"chainmaker.org/chainmaker/smarteditor/session"
)

var _ AuthServerHandler = (*GitLabAuthServerHandler)(nil)

type GitLabAuthServerHandler struct {
}

func (gl GitLabAuthServerHandler) GetAuthServerFlag() string {
	return string(GitLab)
}

func (gl GitLabAuthServerHandler) LoginRedirectHandler(w http.ResponseWriter, r *http.Request, stateCode, site string) {

	oauthUrl := gl.buildOauthUrl(
		conf.Wide.GitLabOAuthServer,
		conf.Wide.GitLabClientId, conf.Wide.PublicServer, stateCode,
		site,
	)

	http.Redirect(w, r, oauthUrl, http.StatusSeeOther)
}

func (gl GitLabAuthServerHandler) LoginCallbackHandler(w http.ResponseWriter, r *http.Request, stateCode, site string) {

	authorizationCode := r.URL.Query().Get("code")
	redirectUrl := GetRedirectUrl(conf.Wide.PublicServer, gl.GetAuthServerFlag(), stateCode, site)

	userInfo, err := gitlab.GetUserInfo(authorizationCode, redirectUrl)
	if err != nil {
		log.Errorf("[GitLabAuthServerHandler] [LoginCallbackHandler] get user info failed, err:%v", err)
		http.Error(w, "get user info failed", http.StatusBadRequest)
		return
	}

	//parse user info
	userId := fmt.Sprintf("%.0f", userInfo["id"].(float64))
	userName := userInfo["username"].(string)
	var avatar string
	if userInfo["avatar_url"] == nil {
		avatar = ""
	} else {
		avatar = userInfo["avatar_url"].(string)
	}

	//handler user login
	session.LoginCallbackHandler(userId, userName, avatar, site, w, r)
}

func (gl GitLabAuthServerHandler) ThirdPartLoginHandler(w http.ResponseWriter, r *http.Request, site string) {
	http.Error(w, "unsupported", http.StatusInternalServerError)
}

func (gl GitLabAuthServerHandler) buildOauthUrl(oauthServer, clientId, publicServer, stateCode, site string) string {
	buffer := bytes.Buffer{}

	//auth server and parameters
	buffer.WriteString(oauthServer)
	buffer.WriteString("/oauth/authorize?")
	buffer.WriteString("client_id=")
	buffer.WriteString(clientId)
	buffer.WriteString("&response_type=code")
	buffer.WriteString("&scope=read_user")
	//redirect url
	buffer.WriteString("&redirect_uri=")
	buffer.WriteString(url.QueryEscape(GetRedirectUrl(publicServer, gl.GetAuthServerFlag(), stateCode, site)))

	return buffer.String()
}
